Skip to main content

13 HTTP协议

HTTP 请求的准备​

浏览器会将 URL 发送给 DNS 服务器,让它解析为 IP 地址,然后建立 TCP 连接。

HTTP 请求的构建​

请求行​

  • GET:去服务器获取资源
  • POST:主动告诉服务端一些信息
  • PUT:向指定资源位置上传最新内容
  • DELETE:用来删除资源

首部字段​

key value,通过冒号分隔

  • Accept-Charset:客户端可以接受的字符集
  • Content-Type:正文的格式
  • Cache-control:控制缓存

HTTP 请求的发送​

发送给每个报文段时,都需要对方有一个回应 ACK,来保证报文可靠地到达了对方。如果没有回应,TCP 层会进行重新传输,直到可以到达。

TCP 层发送每一个报文的时候,都需要加上自己的地址(即源地址)和它想要去的地方(即目标地址),将这两个信息放到 IP 头里面,交给 IP 层进行传输。

IP 层需要查看目标地址和自己是否是在同一个局域网。如果是,就发送 ARP 协议来请求这个目标地址对应的 MAC 地址,然后将源 MAC 和目标 MAC 放入 MAC 头,发送出去即可;如果不在同一个局域网,就需要发送到网关,还要需要发送 ARP 协议,来获取网关的 MAC 地址,然后将源 MAC 和网关 MAC 放入 MAC 头,发送出去。

网关收到包发现 MAC 符合,取出目标 IP 地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的 MAC 地址,将包发给下一跳路由器。

到达目标的局域网,最后一跳的路由器能够发现,目标地址就在自己的某一个出口的局域网上。于是在这个局域网上发送 ARP,获得这个目标地址的 MAC 地址,将包发出去。

目标的机器发现 MAC 地址符合,就将包收起来;发现 IP 地址符合,根据 IP 头中协议项,知道自己上一层是 TCP 协议,于是解析 TCP 的头,里面有序列号,需要看一看这个序列包是不是我要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。

TCP 头里面还有端口号,HTTP 的服务器正在监听这个端口号。于是,目标机器自然知道是 HTTP 服务器这个进程想要这个包,于是将包发给 HTTP 服务器。HTTP 服务器的进程看到,原来这个请求是要访问一个网页,于是就把这个网页发给客户端。

HTTP 返回的构建​

构造好了返回的 HTTP 报文,接下来就是把这个报文发送出去。还是交给 Socket 去发送,还是交给 TCP 层,让 TCP 层将返回的 HTML,也分成一个个小的段,并且保证每个段都可靠到达。

这些段加上 TCP 头后会交给 IP 层,然后把刚才的发送过程反向走一遍。虽然两次不一定走相同的路径,但是逻辑过程是一样的,一直到达客户端。

客户端发现 MAC 地址符合、IP 地址符合,于是就会交给 TCP 层。根据序列号看是不是自己要的报文段,如果是,则会根据 TCP 头中的端口号,发给相应的进程。这个进程就是浏览器,浏览器作为客户端也在监听某个端口。

当浏览器拿到了 HTTP 的报文。发现返回 200,一切正常,于是就从正文中将 HTML 拿出来。HTML 是一个标准的网页格式。浏览器根据这个格式展示出网页。

HTTP 2.0​

HTTP 1.1:

  • 在应用层以纯文本的形式进行通信
  • 每次通信都要带完整的 HTTP 的头

HTTP 2.0:

  • 对 HTTP 的头进行一定的压缩,把大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引
  • 将一个 TCP 的连接中,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。本质是一个虚拟的通道,流可以有优先级
  • 将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。Header 帧用于传输 Header 内容,并且会开启一个新的流。Data 帧用来传输正文实体,多个 Data 帧属于同一个流。

HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。

将三个请求变成三个流,将数据分成帧,乱序发送到一个 TCP 连接中。

QUIC 协议​

HTTP 2.0 的问题:

  • HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序
  • 当其中一个数据包遇到问题,TCP 连接需要等待这个包完成重传之后才能继续进行
  • 后面 stream 的帧会被前面的帧阻塞

自定义连接机制​

基于 UDP,以一个 64 位的随机数作为 ID 来标识

自定义重传机制​

QUIC 序列号是递增的,任何一个序列号的包只发送一次,再次发送时序号加一,RTT 计算相对准确,根据 offset 判定发送的是否为相同内容。

无阻塞的多路复用​

同一条 QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。一个连接上的多个 stream 之间没有依赖。

自定义流量控制​

通过 window_update,来告诉对端它可以接受的字节数。QUIC 的窗口是适应自己的多路复用机制的,不但在一个连接上控制窗口,还在一个连接中的每个 stream 控制窗口。

加载中...